﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;

namespace Sage.Encryption.ServiceExtensions
{

    /// <summary>
    /// 提供加密服务的依赖注入扩展方法
    /// </summary>
    public static class EncryptionServiceExtensions
    {
        /// <summary>
        /// 从配置中添加加密服务到依赖注入容器
        /// </summary>
        [RequiresUnreferencedCode("使用配置绑定可能需要在运行时生成代码")]
        [RequiresDynamicCode("使用配置绑定可能需要在运行时生成代码")]
        public static IServiceCollection AddEncryptionService(this IServiceCollection services, IConfiguration configuration)
        {
            // 考虑到代码裁剪和AOT编译的问题，这里仍使用配置绑定但添加了属性标记
            services.Configure<EncryptionOptions>(configuration.GetSection(EncryptionOptions.SectionName));

            // 注册加密服务
            services.AddScoped<IEncryptionService>(provider =>
            {
                var options = provider.GetRequiredService<IOptions<EncryptionOptions>>().Value;
                return new AesEncryptionService(
                    options.Password,
                    options.Salt,
                    options.Iterations);
            });

            return services;
        }

        /// <summary>
        /// 使用自定义配置添加加密服务到依赖注入容器
        /// </summary>
        public static IServiceCollection AddEncryptionService(
            this IServiceCollection services,
            Action<EncryptionOptions> configureOptions)
        {
            // 配置选项 - 这种方式更适合AOT场景
            services.Configure(configureOptions);

            // 注册加密服务
            services.AddScoped<IEncryptionService>(provider =>
            {
                var options = provider.GetRequiredService<IOptions<EncryptionOptions>>().Value;
                return new AesEncryptionService(
                    options.Password,
                    options.Salt,
                    options.Iterations);
            });

            return services;
        }

        /// <summary>
        /// 添加带有键和IV的加密服务到依赖注入容器
        /// </summary>
        public static IServiceCollection AddEncryptionServiceWithKeyAndIv(
            this IServiceCollection services,
            byte[] key,
            byte[] iv)
        {
            services.AddScoped<IEncryptionService>(_ => new AesEncryptionService(key, iv));
            return services;
        }
    }

}
